/**
 * @file factory_mode_autotest.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_FACTORY_MODE!= 0

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*********************
 *      DEFINES
 *********************/
#define MICPHONE_RECORD_AMR_HEAD_SIZE 6
#define MICPHONE_RECORD_MAX_RECORD_DURATION 3 /*in seconds*/
#define MICPHONE_RECORD_MAX_RECORD_SIZE MICPHONE_RECORD_MAX_RECORD_DURATION * HAL_AMR_BUFSIZE_PER_SECOND + MICPHONE_RECORD_AMR_HEAD_SIZE

/**********************
 *      TYPEDEFS
 **********************/


/**********************
 *  STATIC PROTOTYPES
 **********************/
static void factorymode_autotest_prepare_destory(lv_obj_t * activity_obj);
static void autotest_success_btn_event_cb(lv_obj_t * btn, lv_event_t e);
static void autotest_fail_btn_event_cb(lv_obj_t * btn,lv_event_t e);
static lv_res_t autotest_lcdarea_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param);
static void autotest_lcdcolor_timer_func(void * param);
static void autotest_backlight_change_anim(void * obj, int32_t para);
static lv_autotest_obj_ext_t * autotest_get_ext(void);
static lv_obj_t * autotest_title_create(lv_obj_t * par, watchLangTxtId_t txtId);
static void autotest_resultbtn_create(lv_obj_t * par, uint8_t num);
static lv_obj_t * autotest_list_add(lv_obj_t * list, char * str_t, char * str_c);
static void autotest_testresult_create(lv_obj_t * par, factorymode_test_mode_t res, uint8_t num);
static lv_obj_t * autotest_startbtn_create(lv_obj_t * par, uint8_t num);
static void  autotest_starttest_btn_event_cb(lv_obj_t * btn, lv_event_t e);
static void  autotest_stoptest_btn_event_cb(lv_obj_t * btn, lv_event_t e);
static void autotest_connect_stopbtn_event_cb(lv_obj_t * btn, lv_event_t e);
static void camera_test_destory(void);
static bool autotest_is_testmode_match_obj(void);

extern char * gcvt(double value, int32_t ndigit, char * buf);
/**********************
 *  STATIC VARIABLES
 **********************/

const struct {
    autotest_module_t testitemId;
    watchLangTxtId_t txtId;
    autotest_item_create item_create;
} autotest_itemlist[] = {
    { AUTOTEST_PRESS_KEY, WATCH_TEXT_ID_PRESS_KEY, autotest_presskey_create },
    { AUTOTEST_VERSION_INFO, WATCH_TEXT_ID_VERSION_AND_CALI, autotest_versioninfo_create },
    { AUTOTEST_LCD_TOUCH, WATCH_TEXT_ID_TOUCH_SCR, autotest_lcdarea_create },
    { AUTOTEST_LCD_COLOR, WATCH_TEXT_ID_DISPLAY_SCR, autotest_lcdcolor_create },
    { AUTOTEST_CAMERA, WATCH_TEXT_ID_TR_CAMERA, autotest_camera_create },
    { AUTOTEST_SPEAKER, WATCH_TEXT_ID_SPEAKER, autotest_speaker_create },
    { AUTOTEST_MICPHONE, WATCH_TEXT_ID_MICPHONE, autotest_micphone_create },
    { AUTOTEST_CALL, WATCH_TEXT_ID_CALL, autotest_call_create },
    { AUTOTEST_MEMORY, WATCH_TEXT_ID_MEMORY, autotest_memory_create },
    { AUTOTEST_BACKLIGHT, WATCH_TEXT_ID_BACKLIGHT, autotest_backlight_create },
    { AUTOTEST_GRAVITY, WATCH_TEXT_ID_GRAVITY, autotest_gravity_create },
    { AUTOTEST_BATTERY, WATCH_TEXT_ID_BATTERY, autotest_battery_create },
    { AUTOTEST_VIBRATION, WATCH_TEXT_ID_VIBRATION, autotest_vibration_create },
    { AUTOTEST_WIFI, WATCH_TEXT_ID_TR_WIFI, autotest_wifi_create },
    { AUTOTEST_GPS, WATCH_TEXT_ID_GPS, autotest_gps_create },
    { AUTOTEST_SIMCARD, WATCH_TEXT_ID_SIMCARD, autotest_simcard_create },
};
static lv_signal_cb_t orignal_btn_signal;

/**********************
 *      MACROS
 **********************/
#define  AUTOTEST_LCD_AREA_COUNT  28
#define AUTOTEST_LCDCOLOR_TIME_OUT   3000
/**********************
 *   GLOBAL FUNCTIONS
***********************/
lv_obj_t * factorymode_autotest_create(lv_obj_t * activity_obj)
{
    lv_obj_t * obj;
    if(activity_obj == NULL) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_FACTORY_MODE_AUTOTEST;
        activity_ext.create = factorymode_autotest_create;
        activity_ext.prepare_destory = factorymode_autotest_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
        LV_ASSERT_MEM(activity_obj);
        if(NULL == activity_obj) {
            return NULL;
        }
    }

    obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    if(NULL == obj) {
        return NULL;
    }

    /*Allocate the object type specific extended data*/
    lv_autotest_obj_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_autotest_obj_ext_t));
    LV_ASSERT_MEM(ext);
    if(ext == NULL) return NULL;

    lv_obj_t * bg_cont = lv_cont_create(obj, NULL);
    lv_obj_set_size(bg_cont, LV_HOR_RES, LV_VER_RES);
    lv_obj_add_style(bg_cont, LV_CONT_PART_MAIN, &lv_watch_style_transp);

    ext->par_obj = bg_cont;

    lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();
    ext_fac->testmode = TEST_AUTO;
    ext_fac->lcdarea_click_num = 0;
    ext_fac->speaker_volume = 10;
    ext_fac->buffer = NULL;
    ext_fac->buffer_size = 0;
    ext_fac->timer = NULL;
    ext_fac->record_task = NULL;
    ext_fac->preview_task = NULL;

    factorymode_clear_test_res();
    for(uint8_t i = 0; i < AUTOTEST_ITEM_NUM; i++) {
        if(ext_fac->istest[i] == true) {
            autotest_test_item_create(bg_cont, i);
            break;
        }
    }
    return obj;
}

void autotest_test_item_create(lv_obj_t * par, uint8_t num)
{
    lv_factory_obj_ext_t * ext = factorymode_get_ext();
    while(ext->istest[num] == false && num < AUTOTEST_ITEM_NUM - 1) {
        num = num + 1;
    }
    ext->module = num;
    if(num == AUTOTEST_GPS || num == AUTOTEST_WIFI || num == AUTOTEST_SIMCARD) {
        autotest_connectivity_create(par);
    } else {
        autotest_itemlist[num].item_create(par);
    }
}

watchLangTxtId_t autotest_get_item_textId(uint8_t num)
{
    return autotest_itemlist[num].txtId;
}

#if USE_CRANE_WATCH_KEYPAD
void autotest_key_event(struct keypad_param * arg)
{
    static uint8_t last_event = KEY_EVENT_NONE;
    static uint8_t last_state = LV_INDEV_STATE_REL;
    static uint8_t long_pressed = 0;
    uint32_t txt_id = WATCH_TEXT_ID_KEY_RELEASED;

    if((last_event == arg->key_event) && (last_state == arg->data.state)) {
        return;
    }
    printf("%s: event=%d, state=%d\n", __func__, arg->key_event, arg->data.state);

    lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();
    if((NULL != ext_fac)
            && (AUTOTEST_PRESS_KEY == ext_fac->module)
            && (NULL != ext_fac->label_key_state)) {
        if((KEY_EVENT_POWER_ON == arg->key_event)
                || (KEY_EVENT_LONG_PRESS == arg->key_event)) {
            txt_id = WATCH_TEXT_ID_KEY_LONG_PRESSED;
            long_pressed = 1;
        } else {
            if(LV_INDEV_STATE_PR == arg->data.state) {
                if(0 == long_pressed) {
                    txt_id = WATCH_TEXT_ID_KEY_PRESSED;
                } else {
                    txt_id = WATCH_TEXT_ID_KEY_LONG_PRESSED;
                }
            } else if((KEY_EVENT_CLICK == arg->key_event && LV_INDEV_STATE_REL == arg->data.state)
                      || (KEY_EVENT_RELEASE == arg->key_event && long_pressed)) {
                txt_id = WATCH_TEXT_ID_KEY_RELEASED;
                long_pressed = 0;
            }
        }

        lv_label_set_text_id(ext_fac->label_key_state, txt_id);
        if(txt_id == WATCH_TEXT_ID_KEY_RELEASED) {
            ext_fac->test_res[AUTOTEST_PRESS_KEY] = TEST_SUCCESS;
            autotest_testresult_create(lv_obj_get_parent(ext_fac->label_key_state), TEST_SUCCESS, AUTOTEST_PRESS_KEY + 1);
        }
    }

    last_event = arg->key_event;
    last_state = arg->data.state;
}
#endif

void autotest_presskey_create(lv_obj_t * par)
{
    lv_obj_t * title = autotest_title_create(par, WATCH_TEXT_ID_PRESS_KEY);

    lv_obj_t * label = lv_label_create(par, NULL);
    lv_label_set_text_id(label, WATCH_TEXT_ID_KEY_RELEASED);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_align(label, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 50);

    lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();
    if(NULL != ext_fac) {
        ext_fac->module = AUTOTEST_PRESS_KEY;
        ext_fac->label_key_state = label;
    }

#ifdef BUILD_IN_PC_SIMULATOR
    ext_fac->test_res[AUTOTEST_PRESS_KEY] = TEST_SUCCESS;
    ext_fac->istest[AUTOTEST_PRESS_KEY] = true;
    autotest_testresult_create(lv_obj_get_parent(ext_fac->label_key_state), TEST_SUCCESS, AUTOTEST_PRESS_KEY + 1);
#endif
}

void autotest_versioninfo_create(lv_obj_t * par)
{
    char imei[16];
    char imsi[16];
    lv_obj_t * title = autotest_title_create(par, WATCH_TEXT_ID_VERSION_INFO);

    lv_obj_t * list = lv_list_create(par, NULL);
    lv_obj_set_size(list, LV_HOR_RES, LV_VER_RES * 3 / 4);
    lv_page_set_edge_flash(list, true);
    lv_obj_add_style(list, LV_PAGE_PART_EDGE_FLASH, &lv_watch_cont_opa1);
    lv_obj_align(list, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
    lv_obj_add_style(list, LV_LIST_PART_BG, &lv_watch_style_transp);

    memset(imei, 0, 16);
    memset(imsi, 0, 16);
    watch_modem_get_imei_req(imei);
    watch_modem_get_imsi_req(imsi);
    autotest_list_add(list, (char *)lv_lang_get_text(WATCH_TEXT_ID_VERSION_NUM), app_adaptor_get_version());
    autotest_list_add(list, "IMEI", imei);
    autotest_list_add(list, (char *)lv_lang_get_text(WATCH_TEXT_ID_CALOBRATION), (char *)lv_lang_get_text(WATCH_TEXT_ID_FAIL));
    autotest_list_add(list, "SIM ICCID", imsi);
    autotest_list_add(list, "SN", "123456789ABCDEF");

    autotest_resultbtn_create(par, AUTOTEST_VERSION_INFO);
}

void autotest_lcdarea_create(lv_obj_t * par)
{
    lv_obj_t * cont = lv_cont_create(par, NULL);
    lv_obj_set_size(cont, LV_HOR_RES, LV_VER_RES);
    lv_obj_set_style_local_bg_color(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_cont_set_layout(cont, LV_LAYOUT_GRID);

    uint8_t i = 0;
    lv_obj_t * btn[AUTOTEST_LCD_AREA_COUNT];
    for(i = 0; i < AUTOTEST_LCD_AREA_COUNT; i++) {

        btn[i] = lv_btn_create(cont, NULL);
        lv_obj_set_size(btn[i], (LV_HOR_RES + 3) / 4, (LV_VER_RES + 5) / 7);
        lv_obj_set_style_local_bg_color(btn[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
        lv_obj_set_style_local_border_color(btn[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
        lv_obj_set_style_local_border_width(btn[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 1);
        lv_obj_set_style_local_radius(btn[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
        lv_obj_set_style_local_bg_color(btn[i], LV_BTN_PART_MAIN, LV_STATE_PRESSED, LV_COLOR_GREEN);

        if(0 == i) {
            orignal_btn_signal = lv_obj_get_signal_cb(btn[i]);
        }
        lv_obj_set_signal_cb(btn[i], autotest_lcdarea_btn_signal);
    }
}
static void autotest_lcdslider_event_cb(lv_obj_t * slider, lv_event_t e)
{
    if(LV_EVENT_VALUE_CHANGED == e)
    {
        uint8_t v = lv_slider_get_value(slider);
        HAL_INTENSITY_LEVEL level = (HAL_INTENSITY_LEVEL)(v / 2 + 1);
        Hal_Backlight_Intensity_Set(level);

        lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();
        ext_fac->aging_lcd_brightness = v;
    }
}
static void autotest_cont_event_cb(lv_obj_t * obj, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e) {
        slider_create(NULL, SETTING_LCD_COLOR, 60, autotest_lcdslider_event_cb);
    }
}

void autotest_lcdcolor_create(lv_obj_t * par)
{
    autotest_title_create(par, WATCH_TEXT_ID_LCDTEST);
    autotest_startbtn_create(par, AUTOTEST_LCD_COLOR);
}

void autotest_lcdcolor_aging_create(lv_obj_t * par)
{
    lv_obj_t * cont[10];
    uint8_t i = 0;
    lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();

    ext_fac->aging_lcd_brightness = setting_get_backlight_intensity();

    const lv_style_t * cont_style[] = {
        &(lv_style_pretty),
        &(lv_watch_black_tight),
        &(ext_fac->blue_st),
        &(ext_fac->green_st),
        &(ext_fac->red_st),
        &(ext_fac->orange_st),
        &(ext_fac->purpul_st),
        &(ext_fac->teal_st),
        &(ext_fac->cyan_st),
    };

    for(i = 0; i < 9; i++) {
        cont[i] = lv_cont_create(par, NULL);
        lv_obj_set_size(cont[i], LV_HOR_RES, LV_VER_RES);
        lv_obj_add_style(cont[i], LV_CONT_PART_MAIN, (lv_style_t *)cont_style[i]);
        lv_obj_set_event_cb(cont[i], autotest_cont_event_cb);
    }
    ext_fac->timer = Hal_Timer_Start(AUTOTEST_LCDCOLOR_TIME_OUT, autotest_lcdcolor_timer_func, cont[0], true);
}

uint8_t autotest_aging_lcdtest_get_brightness(void)
{
    lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();
    return ext_fac->aging_lcd_brightness;
}

void autotest_lcdtest_result_create(lv_obj_t * par)
{
    lv_obj_t * title = autotest_title_create(par, WATCH_TEXT_ID_LCDTEST_RESULT);

    lv_obj_t * label_tip = lv_label_create(par, NULL);
    lv_obj_add_style(label_tip, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_label_set_long_mode(label_tip, LV_LABEL_LONG_BREAK);
    lv_obj_set_size(label_tip, LV_HOR_RES, LV_VER_RES / 4);
    lv_label_set_text_id(label_tip, WATCH_TEXT_ID_LCDTEST_TIP);
    lv_label_set_align(label_tip, LV_LABEL_ALIGN_CENTER);
    lv_obj_align(label_tip, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    autotest_resultbtn_create(par, AUTOTEST_LCD_COLOR);
}

static void camera_test_preview_task(lv_task_t * task)
{
    if(autotest_is_testmode_match_obj() == false)
        return;
    lv_factory_obj_ext_t * cameraext = factorymode_get_ext();
    if(Hal_Camera_Preview((uint8_t *)cameraext->img_camera.data)) {
        //update the src of img.
        lv_obj_t * img = (lv_obj_t *)task->user_data;
        lv_img_set_src(img, &cameraext->img_camera);
    }
    lv_task_set_period(cameraext->preview_task, 30);
}

void autotest_camera_create(lv_obj_t * par)
{
    lv_obj_t * cont = lv_cont_create(par, NULL);
    lv_obj_set_size(cont, LV_HOR_RES, LV_VER_RES);
    lv_obj_add_style(cont, LV_CONT_PART_MAIN, &(lv_watch_black_tight));

    cam_start_preview_t cam_params;

    cam_params.width = 240;
    cam_params.height = 240;
    cam_params.sensor_id = 0;
    Hal_Camera_Start_Preview(&cam_params);

    lv_factory_obj_ext_t * cameraext = factorymode_get_ext();
    cameraext->img_camera.header.always_zero = 0;
    cameraext->img_camera.header.w = lv_obj_get_width(lv_obj_get_parent(cont));
    cameraext->img_camera.header.h = lv_obj_get_height(lv_obj_get_parent(cont));
    cameraext->img_camera.data_size = cameraext->img_camera.header.w * cameraext->img_camera.header.h * LV_COLOR_SIZE / 8;
    cameraext->img_camera.header.cf = LV_IMG_CF_TRUE_COLOR;
    cameraext->img_camera.data = lv_mem_alloc(cameraext->img_camera.header.w * cameraext->img_camera.header.h * LV_COLOR_SIZE / 8);
    LV_ASSERT_MEM(cameraext->img_camera.data);
    if(cameraext->img_camera.data == NULL) return;
    memset((void *)cameraext->img_camera.data, 0, cameraext->img_camera.header.w * cameraext->img_camera.header.h * LV_COLOR_SIZE / 8);
    lv_obj_t * img = lv_img_create(cont, NULL);
    lv_img_cache_invalidate_src(&cameraext->img_camera);
    lv_img_set_src(img, &cameraext->img_camera);

    cameraext->preview_task = lv_task_create(camera_test_preview_task, 100, LV_TASK_PRIO_HIGH, (void *)img);

    lv_obj_t * label = lv_label_create(cont, NULL);
    lv_label_set_text_id(label, WATCH_TEXT_ID_CAMERA_TEST);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20_yellow);
    lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 5);

    autotest_resultbtn_create(par, AUTOTEST_CAMERA);
}

void autotest_connectivity_create(lv_obj_t * par)
{
    char str[20];
    lv_obj_t * title = autotest_title_create(par, WATCH_TEXT_ID_CONNECTIVITY);
    lv_factory_obj_ext_t * ext = factorymode_get_ext();
    lv_obj_t * cont = lv_cont_create(par, NULL);
    lv_obj_set_size(cont, 200, LV_VER_RES * 2 / 3);
    lv_obj_align(cont, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 5);
    lv_cont_set_layout(cont, LV_LAYOUT_COLUMN_LEFT);
    lv_obj_add_style(cont, LV_CONT_PART_MAIN, &lv_watch_style_transp);
    if(ext->istest[AUTOTEST_GPS]) {
        lv_obj_t * label_gps = lv_label_create(cont, NULL);
        lv_obj_add_style(label_gps, LV_LABEL_PART_MAIN, &lv_watch_font20);
        memset(str, 0, 20);
        snprintf(str, 20, "%s: %s", "GPS", (char *)lv_lang_get_text(WATCH_TEXT_ID_WAITING));
        lv_label_set_text(label_gps, str);
        ext->test_res[AUTOTEST_GPS] = TEST_FAILED;
    }
    if(ext->istest[AUTOTEST_WIFI]) {
        lv_obj_t * label_wifi = lv_label_create(cont, NULL);
        lv_obj_add_style(label_wifi, LV_LABEL_PART_MAIN, &lv_watch_font20);
        memset(str, 0, 20);
        snprintf(str, 20, "%s: %s", "WIFI", (char *)lv_lang_get_text(WATCH_TEXT_ID_WAITING));
        lv_label_set_text(label_wifi, str);
        ext->test_res[AUTOTEST_WIFI] = TEST_FAILED;
    }
    if(ext->istest[AUTOTEST_SIMCARD]) {
        uint8_t sim = watch_modem_sim_present_check_req();
        lv_obj_t * label_sim = lv_label_create(cont, NULL);
        lv_obj_add_style(label_sim, LV_LABEL_PART_MAIN, &lv_watch_font20);
        memset(str, 0, 20);
        if(sim) {
            snprintf(str, 20, "%s: %s", "SIM", (char *)lv_lang_get_text(WATCH_TEXT_ID_SUCCESS));
            ext->test_res[AUTOTEST_SIMCARD] = TEST_SUCCESS;
        } else {
            snprintf(str, 20, "%s: %s", "SIM", (char *)lv_lang_get_text(WATCH_TEXT_ID_FAIL));
            ext->test_res[AUTOTEST_SIMCARD] = TEST_FAILED;
        }
        lv_label_set_text(label_sim, str);
    }
    lv_obj_t * btn = lv_btn_create(par, NULL);
    lv_obj_t * label = lv_label_create(btn, NULL);
    lv_obj_set_size(btn, LV_HOR_RES / 2, 40);
    lv_label_set_text_id(label, WATCH_TEXT_ID_SKIP);
    lv_obj_align(btn, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -10, -10);
    lv_obj_add_style(label,LV_LABEL_PART_MAIN, &lv_watch_font30);
    lv_obj_set_event_cb(btn, autotest_connect_stopbtn_event_cb);
}

void autotest_wifi_create(lv_obj_t * par)
{
    autotest_title_create(par, WATCH_TEXT_ID_WIFI_TEST);

    lv_obj_t * label = lv_label_create(par, NULL);
    lv_label_set_text_id(label, WATCH_TEXT_ID_WIFI_STATE);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 35);

    lv_obj_t * label_sta = lv_label_create(par, label);
    lv_label_set_text_id(label_sta, WATCH_TEXT_ID_WIFI_OPENING);
    lv_obj_align(label_sta, label, LV_ALIGN_OUT_RIGHT_MID, 20, 0);

    autotest_resultbtn_create(par, AUTOTEST_WIFI);
}

void autotest_gps_create(lv_obj_t * par)
{
    autotest_title_create(par, WATCH_TEXT_ID_GPS_TEST);

    lv_obj_t * label = lv_label_create(par, NULL);
    lv_label_set_text_id(label, WATCH_TEXT_ID_GPS_LOCATING);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 35);

    autotest_resultbtn_create(par, AUTOTEST_GPS);
}

void autotest_speaker_create(lv_obj_t * par)
{
    autotest_title_create(par, WATCH_TEXT_ID_SPEAKER_TEST);
    autotest_startbtn_create(par, AUTOTEST_SPEAKER);
    autotest_resultbtn_create(par, AUTOTEST_SPEAKER);
}

static void micphone_record_play_over_cb(void * para)
{
    if(NULL == para) return;

    lv_factory_obj_ext_t * ext_fac = (lv_factory_obj_ext_t *)para;
    ext_fac->buffer_size = 0;
    if(NULL != ext_fac->buffer) {
        lv_mem_free(ext_fac->buffer);
        ext_fac->buffer = NULL;
    }
    lv_obj_t * par = lv_obj_get_parent(ext_fac->label_key_state);
    lv_obj_del(ext_fac->label_key_state);

    lv_obj_t * btn = lv_obj_get_child_back(par, lv_obj_get_child_back(par, NULL));
    lv_btn_set_state(btn, LV_BTN_STATE_RELEASED);
    lv_label_set_text_id(lv_obj_get_child(btn, NULL), WATCH_TEXT_ID_RETEST);
}

static void micphone_record_task_cb(lv_task_t * task)
{
    uint32_t duration_ms;

    if(NULL == task) return;
    if(autotest_is_testmode_match_obj() == false)
        return;

    lv_factory_obj_ext_t * ext_fac = (lv_factory_obj_ext_t *)task->user_data;

    switch(ext_fac->event) {
        case MCI_EVENT_EOS:
            lv_label_set_text_id(ext_fac->label_key_state, WATCH_TEXT_ID_MICPHONE_RECORD_CHECK);
            Hal_Record_Buffer_Stop_Req(&ext_fac->buffer_size, &duration_ms);
            Hal_Tone_Play_Onetime((uint32_t *)ext_fac->buffer, ext_fac->buffer_size, query_current_volume(), micphone_record_play_over_cb, ext_fac);
            break;
        case MCI_EVENT_ERROR:
            /*recoder stop if value is - 996*/
            ext_fac->buffer_size = 0;
            if(NULL != ext_fac->buffer) {
                lv_mem_free(ext_fac->buffer);
                ext_fac->buffer = NULL;
            }
            break;
        case MCI_EVENT_INFO:
            break;
        default:
            break;
    }
    ext_fac->record_task = NULL;
}

static void micphone_record_cb(MCI_EVNET_T event, MCI_INFO_T info_type, int32_t value)
{
    printf("----------------------event %d, type %d, value %d in micphone_record_cb\n",
           event, info_type, value);

    lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();
    if(NULL == ext_fac) return;
    ext_fac->event = event;
    ext_fac->info_type = info_type;
    ext_fac->value = value;
    if((MCI_EVENT_EOS == event) || (MCI_EVENT_ERROR == event)) {
        ext_fac->record_task = lv_task_create(micphone_record_task_cb, 10, LV_TASK_PRIO_MID, ext_fac);
        lv_task_once(ext_fac->record_task);
    }
}

void autotest_micphone_create(lv_obj_t * par)
{
    autotest_title_create(par, WATCH_TEXT_ID_MICPHONE_TEST);
    autotest_startbtn_create(par, AUTOTEST_MICPHONE);
    autotest_resultbtn_create(par, AUTOTEST_MICPHONE);
}

void autotest_simcard_create(lv_obj_t * par)
{
    uint8_t sim = watch_modem_sim_present_check_req();
    autotest_title_create(par, WATCH_TEXT_ID_SIMCARD_TEST);
    lv_obj_t * label_sim = lv_label_create(par, NULL);
    lv_obj_add_style(label_sim, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_label_set_text_id(label_sim, WATCH_TEXT_ID_SIMCARD);
    lv_obj_align(label_sim, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 50);

    lv_obj_t * label_rec = lv_label_create(par, label_sim);
    lv_obj_align(label_rec, label_sim, LV_ALIGN_OUT_RIGHT_MID, 20, 0);

    lv_obj_t * label_net = lv_label_create(par, label_sim);
    lv_label_set_text_id(label_net, WATCH_TEXT_ID_NETWORK);
    lv_obj_align(label_net, label_sim, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 20);

    lv_obj_t * label_sta = lv_label_create(par, label_sim);
    lv_obj_align(label_sta, label_rec, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 20);

    if(sim == 1) {
        lv_label_set_text_id(label_rec, WATCH_TEXT_ID_RECOGNIZED);

        MMI_MODEM_PLMN_RAT rat;
        watch_modem_get_operator_req(&rat);
        if(MMI_MODEM_PLMN_RAT_LTE == rat) {
            lv_label_set_text(label_sta, "4G");
        } else if(MMI_MODEM_PLMN_RAT_GSM == rat) {
            lv_label_set_text(label_sta, "2G");
        } else {
            lv_label_set_text_id(label_sta, WATCH_TEXT_ID_UNKONWN);
        }
    } else if(sim == 0) {
        lv_label_set_text_id(label_rec, WATCH_TEXT_ID_NOSIM);
        lv_label_set_text_id(label_sta, WATCH_TEXT_ID_UNKONWN);
    }

    autotest_resultbtn_create(par, AUTOTEST_SIMCARD);
}

void autotest_call_create(lv_obj_t * par)
{
    autotest_title_create(par, WATCH_TEXT_ID_CALL_TEST);
    autotest_startbtn_create(par, AUTOTEST_CALL);
    autotest_resultbtn_create(par, AUTOTEST_CALL);
}

void autotest_memory_create(lv_obj_t * par)
{
    lv_mem_monitor_t mon;
    char str[32];
    char mem_value[10];
    float total = 0.0f;
    float free = 0.0f;

    memset(str, 0, 32);
    memset(mem_value, 0, 10);
    lv_mem_monitor(&mon);
    total = mon.total_size / 1024;
    free = mon.free_size / 1024;

    autotest_title_create(par, WATCH_TEXT_ID_MEMORY);

    lv_obj_t * label_t = lv_label_create(par, NULL);
    lv_obj_add_style(label_t, LV_LABEL_PART_MAIN, &lv_watch_font20);
    gcvt(total, 6, mem_value);
    snprintf(str, 32, "%s: %sKB ", (char *)lv_lang_get_text(WATCH_TEXT_ID_MEM_TOTAL), mem_value);
    lv_label_set_text(label_t, str);
    lv_obj_align(label_t, NULL, LV_ALIGN_IN_TOP_LEFT, 20, 50);

    lv_obj_t * label_free = lv_label_create(par, label_t);
    memset(str, 0, 32);
    memset(mem_value, 0, 10);
    gcvt(free, 6, mem_value);
    snprintf(str, 32, "%s: %sKB", (char *)lv_lang_get_text(WATCH_TEXT_ID_MEM_FREE), mem_value);
    lv_label_set_text(label_free, str);
    lv_obj_align(label_free, label_t, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);

    autotest_resultbtn_create(par, AUTOTEST_MEMORY);
}

void autotest_backlight_create(lv_obj_t * par)
{
    lv_obj_t * cont = lv_cont_create(par, NULL);
    lv_obj_set_size(cont, LV_HOR_RES, LV_VER_RES);
    lv_obj_add_style(cont, LV_CONT_PART_MAIN, &lv_style_pretty);

    lv_obj_t * title = autotest_title_create(par, WATCH_TEXT_ID_SCN_BRIGHT);
    lv_obj_add_style(title, LV_LABEL_PART_MAIN, &lv_watch_font20_black);
    autotest_startbtn_create(par, AUTOTEST_BACKLIGHT);
    autotest_resultbtn_create(par, AUTOTEST_BACKLIGHT);
}

void autotest_gravity_create(lv_obj_t * par)
{
    autotest_title_create(par, WATCH_TEXT_ID_GRAVITY);

    lv_obj_t * label = lv_label_create(par, NULL);
    lv_label_set_text_id(label, WATCH_TEXT_ID_FLIP_WATCH);
    lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
    lv_obj_set_width(label, LV_HOR_RES);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_align(label, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 10, -50);

    autotest_resultbtn_create(par, AUTOTEST_GRAVITY);
}

void autotest_battery_create(lv_obj_t * par)
{
    char str[64];
    battery_values_t bat_val;
    uint8_t bat_percent =  Hal_Battery_Get_Status();
    autotest_title_create(par, WATCH_TEXT_ID_BAT_CHG_TEST);

    Hal_Mem_Set(&bat_val, 0, sizeof(battery_values_t));
    Hal_Battery_Get_Values(&bat_val);

    lv_obj_t * label_chg = lv_label_create(par, NULL);
    lv_obj_add_style(label_chg, LV_LABEL_PART_MAIN, &lv_watch_font20);
    memset(str, 0, 64);
    if(Hal_Charger_Get_Status() == HAL_CHG_DISCONNECTED) {
        snprintf(str, 64, "%s %s", (char *)lv_lang_get_text(WATCH_TEXT_ID_CHG_STA), (char *)lv_lang_get_text(WATCH_TEXT_ID_UNCHG));
    } else {
        snprintf(str, 64, "%s %s", (char *)lv_lang_get_text(WATCH_TEXT_ID_CHG_STA), (char *)lv_lang_get_text(WATCH_TEXT_ID_CHARGING));
    }
    lv_label_set_text(label_chg, str);
    lv_obj_align(label_chg, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 40);

    lv_obj_t * label_vol = lv_label_create(par, label_chg);
    memset(str, 0, 64);
    snprintf(str, 64, "%s %dmv", (char *)lv_lang_get_text(WATCH_TEXT_ID_BAT_VOL), bat_val.battery_val_mV);
    lv_label_set_text(label_vol, str);
    lv_obj_align(label_vol, label_chg, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);

    lv_obj_t * label_temp = lv_label_create(par, label_chg);
    memset(str, 0, 64);
    snprintf(str, 64, "%s %d", (char *)lv_lang_get_text(WATCH_TEXT_ID_BAT_TEMP), bat_val.battery_temp);
    lv_label_set_text(label_temp, str);
    lv_obj_align(label_temp, label_vol, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);

    lv_obj_t * label_per = lv_label_create(par, label_chg);
    memset(str, 0, 64);
    snprintf(str, 64, "%s %d", (char *)lv_lang_get_text(WATCH_TEXT_ID_BAT_PERC),  bat_percent);
    lv_label_set_text(label_per, str);
    lv_obj_align(label_per, label_temp, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);

    lv_obj_t * label_sta = lv_label_create(par, label_chg);
    memset(str, 0, 64);
    snprintf(str, 64, "%s %s", (char *)lv_lang_get_text(WATCH_TEXT_ID_BAT_STA), (char *)lv_lang_get_text(WATCH_TEXT_ID_NORMAL));
    lv_label_set_text(label_sta, str);
    lv_obj_align(label_sta, label_per, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);

    autotest_resultbtn_create(par, AUTOTEST_BATTERY);
}

void autotest_vibration_create(lv_obj_t * par)
{
    autotest_title_create(par, WATCH_TEXT_ID_VIBRATION_TEST);
    autotest_startbtn_create(par, AUTOTEST_VIBRATION);
    autotest_resultbtn_create(par, AUTOTEST_VIBRATION);
}

void autotest_hal_stop(void)
{
    lv_factory_obj_ext_t * ext = factorymode_get_ext();
    if(ext->timer){
        Hal_Timer_Stop(ext->timer);
        ext->timer = NULL;
    }
    if(ext->module == AUTOTEST_CAMERA) {
        camera_test_destory();
    } else if(ext->module == AUTOTEST_SPEAKER || ext->module == AUTOTEST_MICPHONE) {
        Hal_Tone_Play_End();
        if(ext->module == AUTOTEST_MICPHONE) {
            if(NULL != ext->record_task) {
                lv_task_del(ext->record_task);
                ext->record_task = NULL;
            }
            uint32_t duration_ms;
            Hal_Record_Buffer_Stop_Req(&ext->buffer_size, &duration_ms);
            ext->buffer_size = 0;
            if(NULL != ext->buffer) {
                lv_mem_free(ext->buffer);
                ext->buffer = NULL;
            }
        }
    } else if(ext->module == AUTOTEST_VIBRATION) {
        Hal_Vibrator_Play_End();
    }
    ext->module = AUTOTEST_MAX;

    if(TEST_AGING == ext->testmode) {
        setting_set_backlight_intensity(setting_get_backlight_intensity(), true);
    }
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

static void factorymode_autotest_prepare_destory(lv_obj_t * activity_obj)
{
    lv_watch_png_cache_all_free();
    autotest_hal_stop();
}

static lv_autotest_obj_ext_t * autotest_get_ext(void)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_FACTORY_MODE_AUTOTEST);
    if(activity_obj == NULL) return NULL;

    lv_obj_t * watch_obj;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);
    if(watch_obj == NULL) return NULL;

    if(watch_obj) {
        lv_autotest_obj_ext_t * ext = lv_obj_get_ext_attr(watch_obj);
        return ext;
    }
    return NULL;
}

static void camera_test_destory(void)
{
    lv_factory_obj_ext_t * cameraext = factorymode_get_ext();
    Hal_Camera_Stop_Preview(0);
    if (NULL != cameraext->img_camera.data) {
        lv_mem_free(cameraext->img_camera.data);
        cameraext->img_camera.data = NULL;
    }
    if (NULL != cameraext->preview_task) {
        lv_task_del(cameraext->preview_task);
        cameraext->preview_task = NULL;
    }
}

static bool autotest_is_testmode_match_obj(void)
{
    if(lv_watch_get_activity_obj(ACT_ID_FACTORY_MODE_MAIN) == NULL)
        return false;
    lv_factory_obj_ext_t * ext = factorymode_get_ext();
    if(ext->testmode == TEST_AUTO && lv_watch_get_top_activity_obj() != lv_watch_get_activity_obj(ACT_ID_FACTORY_MODE_AUTOTEST))
        return false;
    if(ext->testmode == TEST_AGING && lv_watch_get_top_activity_obj() != lv_watch_get_activity_obj(ACT_ID_FACTORY_MODE_AGINGTEST))
        return false;
    if(ext->testmode == TEST_MANUAL && lv_watch_get_top_activity_obj() != lv_watch_get_activity_obj(ACT_ID_FACTORY_MODE_TESTREPORT))
        return false;

    return true;
}

static void autotest_connect_stopbtn_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
        autotest_testresult_create(lv_obj_get_parent(btn), TEST_FAILED, AUTOTEST_ITEM_NUM);
}

static void autotest_fail_btn_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
    {
        lv_factory_obj_ext_t * ext = factorymode_get_ext();
        uint32_t num = lv_obj_get_user_data(btn).user_num;

        if((num == AUTOTEST_SPEAKER) || (num == AUTOTEST_MICPHONE)) {
            Hal_Tone_Play_End();
            if(AUTOTEST_MICPHONE == num) {
                uint32_t duration_ms;
                Hal_Record_Buffer_Stop_Req(&ext->buffer_size, &duration_ms);
                ext->buffer_size = 0;
                if(NULL != ext->buffer) {
                    lv_mem_free(ext->buffer);
                    ext->buffer = NULL;
                }
            }
        } else if(num == AUTOTEST_CAMERA) {
            camera_test_destory();
        } else if(num == AUTOTEST_VIBRATION) {
            Hal_Vibrator_Play_End();
        }

        if(ext->testmode == TEST_AUTO) {
            ext->test_res[num] = TEST_FAILED;
            lv_autotest_obj_ext_t * ext_auto = autotest_get_ext();
            autotest_testresult_create(ext_auto->par_obj, TEST_FAILED, num + 1);
        } else if(ext->testmode == TEST_MANUAL) {
            ext->test_res[num] = TEST_FAILED;
            lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(btn)));
            testreport_update(num);
        } else if(ext->testmode == TEST_AGING) {
            #if USE_LV_WATCH_FACTORYMODE_AGING_MODE != 0
            uint8_t aging_num = 0;
            if(num == AUTOTEST_SPEAKER)aging_num = 0;
            else if(num == AUTOTEST_LCD_COLOR)aging_num = 1;
            else if(num == AUTOTEST_CAMERA)aging_num = 2;
            else if(num == AUTOTEST_CALL)aging_num = 3;
            lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(btn)));
            ext->agingtest_res[aging_num] = TEST_FAILED;
            agingtest_update(aging_num);
            #endif
        }
        factorymode_save_test_res();
    }
}

static void autotest_success_btn_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
    {
        lv_factory_obj_ext_t * ext = factorymode_get_ext();
        uint32_t num = lv_obj_get_user_data(btn).user_num;
        if((num == AUTOTEST_SPEAKER) || (num == AUTOTEST_MICPHONE)) {
            Hal_Tone_Play_End();
            if(AUTOTEST_MICPHONE == num) {
                uint32_t duration_ms;
                Hal_Record_Buffer_Stop_Req(&ext->buffer_size, &duration_ms);
                if(NULL != ext->buffer) {
                    lv_mem_free(ext->buffer);
                    ext->buffer = NULL;
                }
            }
        } else if(num == AUTOTEST_CAMERA) {
            camera_test_destory();
        } else if(num == AUTOTEST_VIBRATION) {
            Hal_Vibrator_Play_End();
        }

        if(ext->testmode == TEST_AUTO) {
            ext->test_res[num] = TEST_SUCCESS;
            lv_autotest_obj_ext_t * ext_auto = autotest_get_ext();
            autotest_testresult_create(ext_auto->par_obj, TEST_SUCCESS, num + 1);
        } else if(ext->testmode == TEST_MANUAL) {
            ext->test_res[num] = TEST_SUCCESS;
            lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(btn)));
            testreport_update(num);
        } else if(ext->testmode == TEST_AGING) {
            #if USE_LV_WATCH_FACTORYMODE_AGING_MODE != 0
            uint8_t aging_num = 0;
            if(num == AUTOTEST_SPEAKER)aging_num = 0;
            else if(num == AUTOTEST_LCD_COLOR)aging_num = 1;
            else if(num == AUTOTEST_CAMERA)aging_num = 2;
            else if(num == AUTOTEST_CALL)aging_num = 3;
            lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(btn)));
            ext->agingtest_res[aging_num] = TEST_SUCCESS;
            agingtest_update(aging_num);
            #endif
        }
        factorymode_save_test_res();
    }
}

static void autotest_stoptest_btn_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
    {
        uint32_t num = lv_obj_get_user_data(btn).user_num;
        if(num == AUTOTEST_SPEAKER) {
            Hal_Tone_Play_End();
        } else if(num == AUTOTEST_VIBRATION) {
            Hal_Vibrator_Play_End();
        }
        lv_obj_del(lv_obj_get_child(lv_obj_get_parent(btn), NULL));
        lv_label_set_text_id(lv_obj_get_child(btn, NULL), WATCH_TEXT_ID_START_TEST);
        lv_obj_set_event_cb(btn, autotest_starttest_btn_event_cb);
    }
}

static void autotest_starttest_btn_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(LV_EVENT_CLICKED == e)
    {
        lv_obj_t * par = lv_obj_get_parent(btn);
        uint32_t num = lv_obj_get_user_data(btn).user_num;
        lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();
        if(num == AUTOTEST_LCD_COLOR) {
            lv_obj_t * cont[6];
            uint8_t i = 0;
            lv_obj_clean(par);
            const lv_style_t * cont_style[5] = {
                &lv_style_pretty,
                &lv_watch_black_tight,
                &(ext_fac->blue_st),
                &(ext_fac->green_st),
                &(ext_fac->red_st),
            };
            for(i = 0; i < 5; i++) {
                cont[i] = lv_cont_create(par, NULL);
                lv_obj_set_size(cont[i], LV_HOR_RES, LV_VER_RES);
                lv_obj_add_style(cont[i], LV_CONT_PART_MAIN, (lv_style_t *)cont_style[i]);
                lv_obj_set_click(cont[i], false);
            }
            ext_fac->timer = Hal_Timer_Start(AUTOTEST_LCDCOLOR_TIME_OUT, autotest_lcdcolor_timer_func, cont[0], true);

        } else if(num == AUTOTEST_SPEAKER) {
            lv_obj_t * label_tip  = lv_obj_get_child(btn, NULL);
            // play tone
            Hal_NFFS_File_Play_Onetime(AUDIO_INCOMING_CALL, query_current_volume(), NULL, NULL);
            lv_label_set_text_id(label_tip, WATCH_TEXT_ID_STOP_TEST);
            lv_obj_set_event_cb(btn, autotest_stoptest_btn_event_cb);

            lv_obj_t * label = lv_label_create(par, NULL);
            lv_label_set_text_id(label, WATCH_TEXT_ID_MUSIC_PLAYING);
            lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
            lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
            lv_obj_add_style(label,LV_LABEL_PART_MAIN, &lv_watch_font20);
            lv_obj_set_width(label, LV_HOR_RES);
            lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 35);
        } else if(num == AUTOTEST_MICPHONE) {
            lv_btn_set_state(btn, LV_BTN_STATE_DISABLED);
            lv_obj_t * label = lv_label_create(par, NULL);
            char * txt1 = (char *)lv_lang_get_text(WATCH_TEXT_ID_MICPHONE_RECORDING);
            char * txt2 = (char *)lv_lang_get_text(WATCH_TEXT_ID_SECONDS);
            char text[50] = {};

            if(LANG_CH == lv_lang_act()) {
                snprintf(text, 50, "%s%d%s", txt1, MICPHONE_RECORD_MAX_RECORD_DURATION, txt2);
            } else {
                snprintf(text, 50, "%s %d%s", txt1, MICPHONE_RECORD_MAX_RECORD_DURATION, txt2);
            }

            lv_label_set_text(label, text);
            lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
            lv_obj_set_width(label, LV_HOR_RES);
            lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
            lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
            lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 35);

            ext_fac->label_key_state = label;
            ext_fac->buffer_size = 0;
            ext_fac->buffer = (uint8_t *)lv_mem_alloc(MICPHONE_RECORD_MAX_RECORD_SIZE);

            Hal_Record_Buffer_Start_Req(ext_fac->buffer,
                                        MICPHONE_RECORD_MAX_RECORD_SIZE,
                                        MICPHONE_RECORD_MAX_RECORD_DURATION * 1000,
                                        micphone_record_cb);
        } else if(num == AUTOTEST_CALL) {
            if(ext_fac->testmode == TEST_AGING) {
                dialpad_create(NULL);
            } else {
                char * number_mo = (char *)Hal_Mem_Alloc(6);
                strncpy(number_mo, "10086", 6);
                phone_voice_call_req(number_mo);
            }
        } else if(num == AUTOTEST_VIBRATION) {
            lv_obj_t * label = lv_label_create(par, NULL);
            lv_label_set_text_id(label, WATCH_TEXT_ID_VIBRATION_PLAYING);
            lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
            lv_obj_set_width(label, LV_HOR_RES);
            lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
            lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
            lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 35);

            lv_label_set_text_id(lv_obj_get_child(btn, NULL), WATCH_TEXT_ID_STOP_TEST);
            lv_obj_set_event_cb(btn, autotest_stoptest_btn_event_cb);

            // play tone
            Hal_Vibrator_Play_Repeat();
        } else if(num == AUTOTEST_BACKLIGHT) {
            lv_obj_t * cont = lv_obj_get_child_back(par, NULL);
            lv_anim_path_t path;
            lv_anim_path_init(&path);
            lv_anim_path_set_cb(&path, lv_anim_path_step);
            lv_anim_t a;
            lv_anim_init(&a);
            lv_anim_set_var(&a, cont);
            lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)autotest_backlight_change_anim);
            lv_anim_set_time(&a, 1);
            lv_anim_set_repeat_count(&a, 1);
            lv_anim_set_repeat_delay(&a, 3000);
            lv_anim_set_path(&a, &path);
            lv_anim_start(&a);
            lv_obj_del(btn);
        }
    }
}

static lv_res_t autotest_lcdarea_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
{
    if((LV_SIGNAL_PRESSED != sign) && (LV_SIGNAL_PRESS_LOST != sign) && (LV_SIGNAL_RELEASED != sign) && (LV_SIGNAL_CONTROL != sign)) {
        return (orignal_btn_signal(btn, sign, param));
    }

    lv_factory_obj_ext_t * ext_fac = NULL;
    if(sign == LV_SIGNAL_PRESSED) {
        if(lv_btn_get_state(btn) == LV_BTN_STATE_RELEASED) {
            ext_fac = factorymode_get_ext();
            ext_fac->lcdarea_click_num++;
            lv_btn_set_state(btn, LV_BTN_STATE_PRESSED);
        }
    } else if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED) {
        lv_btn_set_state(btn, LV_BTN_STATE_PRESSED);
        ext_fac = factorymode_get_ext();
        if(ext_fac->lcdarea_click_num == AUTOTEST_LCD_AREA_COUNT) {
            if(ext_fac->testmode == TEST_AUTO) {
                lv_autotest_obj_ext_t * ext_auto = autotest_get_ext();
                lv_obj_clean(ext_auto->par_obj);
                autotest_testresult_create(ext_auto->par_obj, TEST_SUCCESS, AUTOTEST_LCD_TOUCH + 1);
                ext_fac->test_res[AUTOTEST_LCD_TOUCH] = TEST_SUCCESS;
            } else if(ext_fac->testmode == TEST_MANUAL) {
                ext_fac->test_res[AUTOTEST_LCD_TOUCH] = TEST_SUCCESS;
                lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(lv_obj_get_parent(btn))));
                testreport_update(AUTOTEST_LCD_TOUCH);
                factorymode_save_test_res();
            }
            ext_fac->lcdarea_click_num = 0;

        }
    }
    return LV_RES_OK;
}

static void autotest_lcdcolor_timer_func(void * param)
{
    if(autotest_is_testmode_match_obj() == false)
        return;
    lv_obj_t * obj = (lv_obj_t *)param;
    lv_obj_t * par = lv_obj_get_parent(obj);
    lv_obj_t * child_obj = lv_obj_get_child(par, NULL);
    if(child_obj != obj) {
        lv_obj_del(lv_obj_get_child(par, NULL));
    } else {
        lv_factory_obj_ext_t * ext = factorymode_get_ext();
        if(ext->timer){
            Hal_Timer_Stop(ext->timer);
            ext->timer = NULL;
        }
        lv_obj_clean(par);
        if(TEST_AGING == ext->testmode) {
            setting_set_backlight_intensity(setting_get_backlight_intensity(), true);
        }
        autotest_lcdtest_result_create(par);
    }
}

static void autotest_backlight_change_anim(void * obj, int32_t para)
{
    (void) para;

    static HAL_INTENSITY_LEVEL level =  HAL_INTENSITY_LEVEL_1;
    Hal_Backlight_Intensity_Set(level);
    level ++;
    if(level >  HAL_INTENSITY_LEVEL_5)
        level =  HAL_INTENSITY_LEVEL_1;
}

static void autotest_testresult_time_func(void * param)
{
    if(autotest_is_testmode_match_obj() == false)
        return;
    lv_factory_obj_ext_t * ext = factorymode_get_ext();
    lv_obj_t * par = (lv_obj_t *)param;
    lv_obj_clean(par);
    printf("autotest_testresult_time_func num = %d\n", ext->module);
    ext->timer = NULL;
    if(ext->module == AUTOTEST_ITEM_NUM) {
        lv_obj_del(lv_watch_get_top_activity_obj());
        factorymode_testreport_create(NULL);
        return;
    } else {
        autotest_test_item_create(par, ext->module);
    }
}

static void autotest_testresult_create(lv_obj_t * par, factorymode_test_res_t res, uint8_t num)
{
    lv_factory_obj_ext_t * ext = factorymode_get_ext();
    ext->module = num;

    lv_obj_t * bg = lv_cont_create(par, NULL);
    lv_obj_set_size(bg, LV_HOR_RES, LV_VER_RES);
    lv_cont_set_layout(bg, LV_LAYOUT_CENTER);

    lv_obj_t * label = lv_label_create(bg, NULL);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font30);
    if(res == TEST_SUCCESS) {
        lv_obj_add_style(bg, LV_CONT_PART_MAIN, &ext->green_st);
        lv_label_set_text_id(label, WATCH_TEXT_ID_SUCCESS);
    } else {
        lv_obj_add_style(bg, LV_CONT_PART_MAIN, &ext->red_st);
        lv_label_set_text_id(label, WATCH_TEXT_ID_FAIL);
    }
    ext->timer = Hal_Timer_Start(2000, autotest_testresult_time_func, par, false);
}

static lv_obj_t * autotest_startbtn_create(lv_obj_t * par, uint8_t num)
{
    lv_obj_t * start_btn = lv_btn_create(par, NULL);
    lv_obj_set_size(start_btn, LV_HOR_RES * 2 / 3, 40);
    lv_watch_set_free_num(start_btn, num);
    lv_obj_t * label = lv_label_create(start_btn, NULL);
    lv_label_set_text_id(label, WATCH_TEXT_ID_START_TEST);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font30);
    lv_obj_align(start_btn, NULL, LV_ALIGN_IN_TOP_MID, 0, 80);
    lv_obj_set_event_cb(start_btn, autotest_starttest_btn_event_cb);
    return start_btn;
}

static lv_obj_t * autotest_title_create(lv_obj_t * par, watchLangTxtId_t txtId)
{
    lv_obj_t * label = lv_label_create(par, NULL);
    lv_obj_set_size(label, LV_HOR_RES, LV_VER_RES / 6);
    lv_label_set_text_id(label, txtId);
    lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 5);
    return label;
}

static void autotest_resultbtn_create(lv_obj_t * par, uint8_t num)
{
    lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();

    lv_obj_t * fail_btn = lv_btn_create(par, NULL);
    lv_obj_t * fail_label = lv_label_create(fail_btn, NULL);
    lv_obj_set_size(fail_btn, LV_HOR_RES / 2, LV_VER_RES / 7);
    lv_label_set_text_id(fail_label, WATCH_TEXT_ID_FAIL);
    lv_obj_set_event_cb(fail_btn, autotest_fail_btn_event_cb);
    lv_obj_add_style(fail_btn, LV_BTN_PART_MAIN, &(ext_fac->red_st));
    lv_obj_align(fail_btn, par, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
    lv_watch_set_free_num(fail_btn, num);

    lv_obj_t * suc_btn = lv_btn_create(par, fail_btn);
    lv_obj_t * suc_label = lv_label_create(suc_btn, NULL);
    lv_label_set_text_id(suc_label, WATCH_TEXT_ID_SUCCESS);
    lv_obj_set_event_cb(suc_btn, autotest_success_btn_event_cb);
    lv_obj_add_style(suc_btn, LV_BTN_PART_MAIN, &(ext_fac->green_st));
    lv_obj_align(suc_btn, fail_btn, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
    ext_fac->suc_btn = suc_btn;
}

static lv_obj_t * autotest_list_add(lv_obj_t * list, char * str_t, char * str_c)
{
    /*Create a list element with the image an the text*/
    lv_obj_t * btn;
    btn = lv_btn_create(list, NULL);

    /*Save the original signal function because it will be required in `lv_list_btn_signal`*/
    lv_list_set_ancestor_btn_signal(btn);

    lv_factory_obj_ext_t * ext_fac = factorymode_get_ext();
    /*Set the default styles*/
    lv_obj_add_style(btn, LV_BTN_PART_MAIN,  &(ext_fac->list_btn_st));

    lv_page_glue_obj(btn, true);
    lv_obj_add_protect(btn, LV_PROTECT_PRESS_LOST);
    lv_obj_set_signal_cb(btn, lv_list_get_listbtn_signal());

    /*Make the size adjustment*/
    lv_coord_t w = lv_obj_get_width(list);
    uint8_t pad_w = w - 8;
    lv_obj_set_width(btn, pad_w);

    lv_obj_t * label_t = lv_label_create(btn, NULL);
    lv_label_set_long_mode(label_t, LV_LABEL_LONG_SROLL);
    lv_obj_set_size(label_t, pad_w, lv_obj_get_height(list) / 8);
    lv_obj_set_pos(label_t, 20, 0);
    lv_obj_add_style(label_t, LV_LABEL_PART_MAIN, &lv_watch_font20);
    lv_label_set_text(label_t, str_t);
    lv_obj_set_click(label_t, false);

    lv_obj_t * label_c = lv_label_create(btn, label_t);
    lv_label_set_text(label_c, str_c);
    lv_obj_align(label_c, label_t, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
    return btn;
}

#endif /*USE_LV_WATCH_FACTORY_MODE*/
